package drds.configuration.db.xml_mapping.sql_execute;

import drds.configuration.db.xml_mapping.annotation.dto.Dto;
import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;

import java.lang.reflect.*;
import java.math.BigDecimal;
import java.util.HashSet;
import java.util.List;
import java.util.Set;


public class ReturnTypeResolver {
    //classType
    public static final Set<Class> classTypeSet = new HashSet<Class>();
    public static final Set<String> classTypeNameSet = new HashSet<String>();

    static {
        classTypeSet.add(Void.class);//入参的时候没有
        //
        classTypeSet.add(boolean.class);
        classTypeSet.add(Boolean.class);
        //
        classTypeSet.add(int.class);
        classTypeSet.add(Integer.class);
        //
        classTypeSet.add(long.class);
        classTypeSet.add(Long.class);
        //
        classTypeSet.add(String.class);
        classTypeSet.add(BigDecimal.class);
        for (Class classType : classTypeSet) {
            classTypeNameSet.add(classType.getName());
        }
    }

    public static Type resolve(Method method, MapperMethodSignature mapperMethodSignature) {
        Type genericReturnType = method.getGenericReturnType();
        if (genericReturnType instanceof TypeVariable) {
            throw new IllegalArgumentException("不支持:" + TypeVariable.class.getSimpleName());
        } else if (genericReturnType instanceof GenericArrayType) {
            throw new IllegalArgumentException("不支持:" + GenericArrayType.class.getSimpleName());
        } else if (genericReturnType instanceof ParameterizedType) {
            //
            ParameterizedType parameterizedType = (ParameterizedType) genericReturnType;
            if (parameterizedType.getRawType() == java.util.Map.class || parameterizedType.getRawType() == List.class) {
                if (parameterizedType.getRawType() == java.util.Map.class) {
                    //map只支持Map<String,Object>类型
                    if ((parameterizedType.getActualTypeArguments()[0].getTypeName() == String.class.getName()//
                            &&//
                            parameterizedType.getActualTypeArguments()[1].getTypeName() == Object.class.getName()//
                    )) {
                        mapperMethodSignature.setReturnsMap(true);
                    } else {
                        throw new IllegalArgumentException("map只支持Map<String,Object>类型");
                    }
                    //List
                } else if (parameterizedType.getRawType() == List.class) {
                    //只支持Map<String,Object> or @Dto or基本类型
                    Type type = parameterizedType.getActualTypeArguments()[0];
                    if (!(type instanceof ParameterizedType)) {
                        String className = type.getTypeName();
                        Class clazz = null;
                        try {
                            clazz = Class.forName(className);
                        } catch (ClassNotFoundException e) {
                            e.printStackTrace();
                        }
                        Dto dto = (Dto) clazz.getAnnotation(Dto.class);
                        if (dto != null) {
                            mapperMethodSignature.setReturnsList(true);
                            mapperMethodSignature.setReturnsDto(true);
                            mapperMethodSignature.setDtoClass(clazz);
                        } else {
                            //基本类型
                            String classTypeName = type.getTypeName();
                            if (classTypeNameSet.contains(classTypeName)) {
                                mapperMethodSignature.setReturnsList(true);
                                mapperMethodSignature.setReturnsBasicType(true);
                            } else {
                                throw new IllegalArgumentException("list复合类型只支持" + Dto.class.getName() + "类型/map/基本,暂时不支持其他的数据类型");
                            }

                        }

                    } else {
                        ParameterizedTypeImpl parameterizedType2 = (ParameterizedTypeImpl) type;
                        if (parameterizedType2.getRawType().getTypeName().equals(java.util.Map.class.getName())) {
                            //list<map<String,Object>>
                            if ((parameterizedType2.getActualTypeArguments()[0].getTypeName() == String.class.getName()//
                                    &&//
                                    parameterizedType2.getActualTypeArguments()[1].getTypeName() == Object.class.getName()//
                            )) {
                                //
                                mapperMethodSignature.setReturnsList(true);
                                mapperMethodSignature.setReturnsMap(true);
                            } else {
                                throw new IllegalArgumentException("list复合类型只支持" + Dto.class.getName() + "类型/map/基本,暂时不支持其他的数据类型");
                            }
                        } else {
                            throw new IllegalArgumentException("list复合类型只支持" + Dto.class.getName() + "类型/map/基本,暂时不支持其他的数据类型");
                        }
                    }
                } else {
                    throw new IllegalArgumentException("暂时不支持其他的数据类型");
                }
            } else {
                throw new IllegalArgumentException("复杂类型只支持list map");
            }
        } else {
            String className = genericReturnType.getTypeName();
            if (classTypeSet.contains(genericReturnType) || classTypeNameSet.contains(className)) {
                //
                mapperMethodSignature.setReturnsList(false);
                mapperMethodSignature.setReturnsBasicType(true);
            } else {
                if ("void".equals(className)) {
                    mapperMethodSignature.setReturnsVoid(true);
                } else {
                    Class clazz = null;
                    try {
                        clazz = Class.forName(className);
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    }
                    Dto dto = (Dto) clazz.getAnnotation(Dto.class);
                    if (dto != null) {
                        mapperMethodSignature.setReturnsList(false);
                        mapperMethodSignature.setReturnsDto(true);
                        mapperMethodSignature.setDtoClass(clazz);
                    } else {
                        throw new IllegalArgumentException("单个元素只支持" + Dto.class.getName() + "/基本类型,暂时不支持其他的数据类型");
                    }
                }
            }
        }
        return genericReturnType;
    }


}
